﻿#include <Sys\RenderUnit\SysRenderDatagram\CONTROLATTRIBRD.HPP>
#include <Render\Render_Win32\Render_Win32_D3D\RENDER_WIN32_D3D9.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>

using namespace CxxlMan;
using namespace Cxxl3D;

class CControlAttribDD_D3D9:public IDatagramDisposal_D3d9, public IControlAttribBridge
{

  class CControlAttrib_CEO:public IControlAttrib_CEO
  {
    LPDIRECT3DDEVICE9 m_pDEVICE9;

    // 正反面剔除模式 Mode = 1:剔除順時鐘面  -1:剔除反時鐘面 -2:不剔除
    virtual void cxxlFASTCALL Cull(char CullMode)
    {

      DWORD CMode;
      switch(CullMode)
      {
      case -1:
        CMode = D3DCULL_CCW;
        break;
      case 1:
        CMode = D3DCULL_CW;
        break;
      case -2:
        CMode = D3DCULL_NONE;
      }

      m_pDEVICE9->SetRenderState(D3DRS_CULLMODE, CMode);
    }

    // 多邊形填充模式 FillMode = 1:畫面  -1:畫線 -2:畫點
    virtual void cxxlFASTCALL Fill(char FillMode)
    {
      DWORD CMode;
      switch(FillMode)
      {
      case 1:
        CMode = D3DFILL_SOLID;
        break;
      case -1:
        CMode = D3DFILL_WIREFRAME;
        break;
      case -2:
        CMode = D3DFILL_POINT;
      }
      m_pDEVICE9->SetRenderState(D3DRS_FILLMODE, CMode);
    }

    // 是否使用內插(GL_SMOOTH) ShadeMode = true:是  false:否
    virtual void cxxlFASTCALL ShadeModel(bool ShadeMode)
    {
      if(ShadeMode)
        m_pDEVICE9->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);
      else
        m_pDEVICE9->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_FLAT);
    }

    // 設定貼圖座標模式 Mode = 2:Repeat 1:Mirror -1:ClampEdge -2:ClampBorder
    /*
    virtual void TextureAddrMode(char Mode)
    {
      D3DTEXTUREADDRESS mode;
      switch(Mode)
      {
      case 2:
        mode = D3DTADDRESS_WRAP;
        break;
      case 1:
        mode = D3DTADDRESS_MIRROR;
        break;
      case -1:
        mode = D3DTADDRESS_CLAMP;
        break;
      case -2:
        mode = D3DTADDRESS_BORDER;
        break;
      }
      m_pDEVICE9->SetSamplerState(0, D3DSAMP_ADDRESSU, mode);
      m_pDEVICE9->SetSamplerState(0, D3DSAMP_ADDRESSV, mode);
    }
    */

    // TextureAddrMode() 指定為 ClampBorder 時，所用的顏色
    /*
    virtual void TextureClampBorderColor(char R, char G, char B, char A)
    {
      m_pDEVICE9->SetSamplerState(0, D3DSAMP_BORDERCOLOR, D3DCOLOR_RGBA(R,G,B,A));
    }
    */

    // 貼圖的 Mipmap 模式 Mode = 2:None 1:Bilinear -1:Trilinear -2:Anisotropic filter
    /*
    virtual void TextureMipmapMode(char Mode)
    {
      switch(Mode)
      {
      case 2:
        // 貼圖被放大時, 取最接近4個點來內插
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
        // 貼圖被縮小時, 取最接近4個點來平均
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        // 不使用Mipmap
		    m_pDEVICE9->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
        break;
      case 1:
        // 貼圖被放大時, 取最接近4個點來內插
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
        // 貼圖被縮小時, 取最接近4個點來平均
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        // 取最接近大小的圖層
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
        break;
      case -1:
        // 貼圖被放大時, 取最接近4個點來內插
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
        // 貼圖被縮小時, 取最接近4個點來平均
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        // 取最接近大小的兩個圖層, 然後再內插
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
        break;
      case -2:
        // 會根據縮放的長寬比例來取用貼圖, 不固定是取哪幾個圖
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 8);
        // 取最接近大小的兩個圖層, 然後再內插
        m_pDEVICE9->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
      }
    }
    */

    // 是否為 Normalize 做正規化處理
    // Switch = true:是  false:否
    virtual void cxxlFASTCALL AutoNormalize(bool Switch)
    {
      m_pDEVICE9->SetRenderState(D3DRS_NORMALIZENORMALS, Switch);
    }


  public:
    CControlAttrib_CEO()
    {
    }
    virtual ~CControlAttrib_CEO(){}

    void cxxlFASTCALL SetDEVICE9(LPDIRECT3DDEVICE9 pDEVICE9)
    {
      m_pDEVICE9 = pDEVICE9;
    }
  }Attrib_CEO;

  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterD3d> &IRenderDatagramDisposalCenterD3d_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, LPDIRECT3DDEVICE9 pDEVICE9)
  {
    if(actIControlAttribRD_Ptr.isNULL())
    {
      if(IRenderDatagram_Arg.isNULL() == false)
      {
        actIControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
        Attrib_CEO.SetDEVICE9(pDEVICE9);
        SetAll(actIControlAttribRD_Ptr, &Attrib_CEO);
      }
    }
    else if(isModified(actIControlAttribRD_Ptr))
    {
      if(IRenderDatagram_Arg.isNULL() == false)
        actIControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);

      Attrib_CEO.SetDEVICE9(pDEVICE9);
      SetAll(actIControlAttribRD_Ptr, &Attrib_CEO);
    }
    else if(IRenderDatagram_Arg.isNULL() == false)
    {
      Smart_Ptr<IControlAttribRD> IControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
      if((IControlAttribRD*)actIControlAttribRD_Ptr != (IControlAttribRD*)IControlAttribRD_Ptr)
      {
        Attrib_CEO.SetDEVICE9(pDEVICE9);
        Chk(actIControlAttribRD_Ptr, IControlAttribRD_Ptr, &Attrib_CEO);
        actIControlAttribRD_Ptr = IControlAttribRD_Ptr;
      }
    }

    return true;
  }

  Smart_Ptr<IControlAttribRD> actIControlAttribRD_Ptr;

public:
  // Consteructor
  CControlAttribDD_D3D9()
    :cxxlObject(Spirit_Easy),
    actIControlAttribRD_Ptr(NULL,this)
  {
  }

  // Desteructor
  virtual ~CControlAttribDD_D3D9()
  {
  }

};

cxxlObject *cxxlFASTCALL New_CControlAttribDD_D3D9()
{
  return new CControlAttribDD_D3D9;
}